<template>
	<div class="el-upload">
		<div class="el-upload_content" @click="upload">
			<div ref="message" class="el-upload_text">点击上传文件</div>
		</div>
		<div class="el-upload-progress" :style="{width: `${progress}%`}" />
		<input class="el-upload_input" type="file" :id="randomId" @change="onchange($event)" />
	</div>
</template>

<script>
	import axios from 'axios'
	import md5 from 'js-md5';
	export default {
		name: 'el-file-upload',
		props: {
			// 文件上传类型限制
			accept: {
				type: String,
				require: false,
				default: '.png,.jpg,.pdf'
			},
			chunk: {
				type: Boolean,
				require: false,
				default: false
			},
		},
		data() {
			return {
				file: null,
				fileMD5: null,
				fileType: null,
				chunkSize: 1024*1024,
				concurrent: 2, //最大并发数量
				progress: 0, //进度
			}
		},
		computed: {
			isSelectFile() {
				return this.file != null;
			},
			randomId() {
				var id = "";
				for (var i = 0; i < 6; i++) {
					id += Math.floor(Math.random() * 10);
				}
				return id;
			}
		},
		methods: {
			upload() {
				const inputEvent = document.getElementById(this.randomId);
				if (!inputEvent) return;
				inputEvent.click();
			},
			onchange(e) {
				this.file = e.target.files[0];
				// console.log(this.file)
				this.$refs.message.innerText = "等待文件上传..";
				// 获取文件MD5值
				let fileRederInstance = new FileReader();
				fileRederInstance.readAsBinaryString(this.file);
				fileRederInstance.addEventListener('load', e => {
					let fileBolb = e.target.result;
					this.fileMD5 = md5(fileBolb);
					let index = this.file.name.lastIndexOf('.')
					this.fileType = this.file.name.substring(index + 1, this.file.name.length)
					// let form = new FormData()
					// form.append('file', this.file)
					// form.append('name', this.fileMD5)
					this.$refs.message.innerText = "开始上传..";
					// 判断是否是需要分片
					if (this.chunk) {
						console.log('开始上传')
						this.uploadChunkFile(this.file);
					}
					this.$emit('onchange', this.file);
				});
			},
			// 分片上传
			uploadChunkFile(file) {
				var chunkList = []; //分片列表
				var process = 0; //进度	
				var chunk_size = this.chunkSize; //分片大小
				var upload_size = 0;
				var chunk_index = 0; //分片序号
				const chunk_count = Math.ceil(file.size / chunk_size) //总片数
				// 判断是否是需要分片并发上传或直接上传
				if (file.size > chunk_size) {
					// 文件切片
					while (chunk_index < chunk_count) {
						const chunk_file = file.slice(upload_size, upload_size + chunk_size);
						// const chunkfile = new File([chunkInfo.file], chunkInfo.name);
						chunk_index += 1;
						upload_size += chunk_size;
						const chunkInfo = {
							md5: this.fileMD5,
							name: file.name,
							type: file.type,
							file: chunk_file,
							size: chunk_file.size,
							total: chunk_count,
							index: chunk_index
						}
						chunkList.push(chunkInfo);
					}
					this.$refs.message.innerText = "正在上传文件"
					this.concurrentUpload(chunkList)
				} else {
					console.log('直接上传')
				}
			},
			//进度条
			setProgress(number) {
				this.progress = number;
			},
			/***
			 * 并发上传
			 **/
			concurrentUpload(chunkList) {
				let concurrent = this.concurrent;
				let progress = 0;
				const concurrentExecution = (list, limit, asyncHandle) => {
					// 递归执行
					let recursion = (arr) => {
						// 执行方法 arr.shift() 取出并移除第一个数据
						return asyncHandle(arr.shift()).then(() => {
							// 数组还未迭代完，递归继续进行迭代
							if (arr.length !== 0) {
								return recursion(arr)
							} else {
								return 'finish'
							}
						})
					}
					// 创建新的并发数组
					let listCopy = [].concat(list)
					// 正在进行的所有并发异步操作
					let asyncList = []
					limit = limit > listCopy.length ? listCopy.length : limit
					while (limit--) {
						asyncList.push(recursion(listCopy))
					}
					// 所有并发异步操作都完成后，本次并发控制迭代完成
					return Promise.all(asyncList)
				}
				// 并发执行
				concurrentExecution(chunkList, concurrent, (chunkItem) => {
					return new Promise((resolve, reject) => {
						var progress = parseInt((chunkItem.index / chunkItem.total) * 100)
						// console.log(chunkItem)
						let formData = new FormData();
						formData.append('file', chunkItem.file)
						formData.append('name', chunkItem.name)
						formData.append('uuid', chunkItem.md5)
						formData.append('total', chunkItem.total)
						formData.append('chunk', chunkItem.index)
						formData.append('type', this.fileType)
						this.$_http.upload(formData).then((res)=>{
							console.log(res)
							this.setProgress(progress);
							resolve()
						})
						// axios({
						// 		method: 'post',
						// 		url: 'http://127.0.0.1:8000/uploadfile',
						// 		data: formData
						// 	})
						// 	.then((response) => {
						// 		console.log(response, 'success')
						// 		// resolve()
						// 	}).catch(err => {
						// 		// resolve()
						// 		console.log(err, 'error')
						// 	});
						// axios({
						// 		method: 'post',
						// 		url: 'http://192.168.0.184:6355/hostool/file/sliceUploadFiles',
						// 		data: formData
						// 	})
						// 	.then((response) => {
						// 		console.log(response, 'success')
						// 		// resolve()
						// 	}).catch(err => {
						// 		// resolve()
						// 		console.log(err, 'error')
						// 	});
						
						// console.log(chunkItem)
						// setTimeout(() => {
						// 	resolve()
						// }, 2000)
					})
				}).then(res => {
					console.log('执行完成', res)
					this.$refs.message.innerText = "上传完成"
				})
			},
			createUploadData(chunkInfo) {
				let formData = new FormData();
				formData.append('file', chunkInfo.file)
				formData.append('name', chunkInfo.name)
				formData.append('type', chunkInfo.type)
				formData.append('size', chunkInfo.size)
				formData.append('total', chunkInfo.total)
				formData.append('index', chunkInfo.index)
				return formData
			}
		}
	}
</script>

<style scoped lang="scss">
	.el-upload {
		background-color: #fff;
		border: 1px dashed #d9d9d9;
		border-radius: 6px;
		box-sizing: border-box;
		width: 260px;
		height: 120px;
		display: inline-block;
		text-align: center;
		cursor: pointer;
		position: relative;
		overflow: hidden;
		transition: all 0.28s ease;

		&:hover {
			border-color: #409eff;

			.el-upload_text {
				color: #409eff;
			}
		}

		.el-upload-progress {
			position: absolute;
			bottom: 0;
			z-index: 1;
			width: 0%;
			height: 100%;
			background-color: #f0f7ff;
			transition: all 0.28s ease;
		}

		.el-upload_content {
			position: absolute;
			z-index: 2;
			width: 100%;
			height: 100%;
			display: flex;
			justify-content: center;
			align-items: center;
		}

		.el-upload_text {
			text-align: center;
			color: #606266;
		}

		.el-upload_input {
			display: none;
		}
	}
</style>
